package hashmvp.superbloomfilter.config;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Properties;




public class ConfigurationManager {

    private static Properties properties = null;

    private static String license;
    
    private final static int RECURSION_LIMIT = 9;
    
    private static String rootpath;
    
   public static void setRootpath(String path){
	   rootpath =path;
   }
    
    /****************************************************
     * @methode	getProperty
     * @note 	
     * @param property
     * @return
     */
    public static String getProperty(String property)
    {
        if (properties == null) {
            loadConfig("setup.cfg");  //原�?�为null
        }
        String tem=properties.getProperty(property);
        return tem;
    }

    
    /****************************************************
     * Get a configuration property as an integer
     * 
     * @param property
     *            the name of the property
     * 
     * @return the value of the property. <code>0</code> is returned if the
     *         property does not exist. To differentiate between this case and
     *         when the property actually is zero, use <code>getProperty</code>.
     */
    public static int getIntProperty(String property)
    {
        if (properties == null){
            loadConfig("setup.cfg");
        }

        String stringValue = properties.getProperty(property);
        int intValue = 0;

        if (stringValue != null){
            try{
                intValue = Integer.parseInt(stringValue.trim()); 
            }catch (NumberFormatException e){
            	e.printStackTrace();
                //SystemInfo.warn(LogLevel.L1, " Warning: Number format error in property: " + property);
            }
        }

        return intValue;
    }

    
    /****************************************************
     * Get a configuration property as a boolean. True is indicated if the value
     * of the property is <code>TRUE</code> or <code>YES</code> (case
     * insensitive.)
     * 
     * @param property
     *            the name of the property
     * 
     * @return the value of the property. <code>false</code> is returned if
     *         the property does not exist. To differentiate between this case
     *         and when the property actually is false, use
     *         <code>getProperty</code>.
     */
    public static boolean getBooleanProperty(String property)
    {
        return getBooleanProperty(property, false);
    }

    
    /****************************************************
     * Get a configuration property as a boolean, with default.
     * True is indicated if the value
     * of the property is <code>TRUE</code> or <code>YES</code> (case
     * insensitive.)
     *
     * @param property
     *            the name of the property
     *
     * @param defaultValue
     *            value to return if property is not found.
     *
     * @return the value of the property. <code>default</code> is returned if
     *         the property does not exist. To differentiate between this case
     *         and when the property actually is false, use
     *         <code>getProperty</code>.
     */
    public static boolean getBooleanProperty(String property, boolean defaultValue)
    {
        if (properties == null)
        {
            loadConfig("setup.cfg");
        }

        String stringValue = properties.getProperty(property);

        if (stringValue != null)
        {
        	stringValue = stringValue.trim();
            return  stringValue.equalsIgnoreCase("true") ||
                    stringValue.equalsIgnoreCase("yes");
        }
        else
        {
            return defaultValue;
        }
    }

    /****************************************************
     * Returns an enumeration of all the keys in the DSpace configuration
     * 
     * @return an enumeration of all the keys in the DSpace configuration
     */
    @SuppressWarnings("unchecked")
    public static Enumeration propertyNames()
    {
        if (properties == null)
            loadConfig("setup.cfg");

        return properties.propertyNames();
    }

    /****************************************************
     * Get the site-wide default license that submitters need to grant
     * 
     * @return the default license
     */
    public static String getDefaultSubmissionLicense()
    {
        if (properties == null)
        {
            loadConfig("setup.cfg");
        }

        return license;
    }

    /****************************************************
     * Get the path for the news files.
     * 
     */
    public static String getNewsFilePath()
    {
        String filePath = ConfigurationManager.getProperty("dspace.dir")
                + File.separator + "config" + File.separator;

        return filePath;
    }

    /****************************************************
     * Writes license to a text file.
     * 
     * @param news
     *            the text to be written to the file.
     */
    public static void writeLicenseFile(String newLicense)
    {
        String licenseFile = getProperty("dspace.dir") + File.separator
                             + "config" + File.separator + "default.license";
        try
        {
            // write the news out to the appropriate file
            FileOutputStream fos = new FileOutputStream(licenseFile);
            OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8");
            PrintWriter out = new PrintWriter(osr);
            out.print(newLicense);
            out.close();
        }
        catch (IOException e)
        {
        	e.printStackTrace();
        	//SystemInfo.error(LogLevel.L1, "license_write: " + e.getLocalizedMessage());
        }

        license = newLicense;
     }

    private static File loadedFile = null;

    
    /****************************************************
     * Return the file that configuration was actually loaded from. Only returns
     * a valid File after configuration has been loaded.
     * 
     * @return File naming configuration data file, or null if not loaded yet.
     */
    public static File getConfigurationFile()
    {
        // in case it hasn't been done yet.
        loadConfig("setup.cfg");

        return loadedFile;
    }

    /****************************************************
     * Load the DSpace configuration properties. Only does anything if
     * properties are not already loaded. Properties are loaded in from the
     * specified file, or default locations.
     * 
     * @param configFile
     *            The <code>dspace.cfg</code> configuration file to use, or
     *            <code>null</code> to try default locations
     */
    @SuppressWarnings("unchecked")
    public  static void loadConfig(String configFile) {
        if (properties != null && configFile == null)
            return;
    	InputStream is = null;
    	
    	try {

            if (rootpath==null)
            	rootpath="";
            
    		is = new FileInputStream(rootpath+configFile);
            
            //Convert the config file utf-8 code to support chinese.
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(rootpath+configFile), "utf-8"));
            
            loadedFile = new File(configFile);
 
            if (is == null){
                throw new RuntimeException("Cannot find " + configFile);
            }
            else{
            	if(properties == null){
            		properties = new Properties();
            	}
//              properties.load(is);
            	properties.load(br);
            	
            	//֧����#ע��
                
            	// walk values, interpolating any embedded references.
               
            	for (Enumeration pe = properties.propertyNames(); pe.hasMoreElements(); ){
                    String key = (String)pe.nextElement();
                    String value = interpolate(key, 1);
                    if (value != null)
                        properties.setProperty(key,value);
                }
            }

            br.close();
            is.close();

        }
        catch (IOException e)
        {
        	throw new RuntimeException("Cannot find " + configFile);
        }
    }

    /****************************************************
     * Recursively interpolate variable references in value of
     * property named "key".
     * @return new value if it contains interpolations, or null
     *   if it had no variable references.
     */
    private static String interpolate(String key, int level) {
        if (level > RECURSION_LIMIT)
            throw new IllegalArgumentException("ConfigurationManager: Too many levels of recursion in configuration property variable interpolation, property="+key);
        String value = (String)properties.get(key);
        int from = 0;
        StringBuffer result = new StringBuffer();//null; //cy
        while (from < value.length())
        {
            int start = value.indexOf("${", from);
            if (start >= 0)
            {
                int end = value.indexOf("}", start);
                if (end < 0)
                    break;
                String var = value.substring(start+2, end);
                if (result == null)
                    result = new StringBuffer(value.substring(from, start));
                else
                    result.append(value.substring(from, start));
                if (properties.containsKey(var))
                {
                    String ivalue = interpolate(var, level+1);
                    if (ivalue != null)
                    {
                        result.append(ivalue);
                        properties.setProperty(var, ivalue);
                    }
                    else
                        result.append(properties.getProperty(var));
                }
                else
                {
                	System.out.println("Interpolation failed in value of property \""+key+
                             "\", there is no property named \""+var+"\"");
                }
                from = end+1;
            }
            else
                break;
        }
        if (result != null && from < value.length())
            result.append(value.substring(from));
        return (result == null) ? null : result.toString();
    }
}

